#include <stdio.h>
#include <iostream>
#include <string>
#include <fstream>
#include <time.h>
#include <math.h>
#include "/usr/local/include/ni488.h"
#include <vector>
#include <assert.h>

using namespace std;

void output_help() {
  cout << endl << endl;
  cout << "Run Program with the following: " << endl;
  cout << "./teksoft [filename] ch=[channels] [traces] [fastframe] [maxtime]" << endl;
  cout << " [filename]: this is the base of the filename used for the output.  (e.g. 'mydata' will produce files mydata_traces.bin and mydata_header.txt)" << endl; 
  cout << " [channels]: Channels to be read (e.g. 'ch=2' reads channels 1,2 'ch=4' reads channels 1,2,3,4)" << endl;
  cout << " [traces]: Number of traces to be stored (e.g. '10000' takes 10000 traces)" << endl;
  cout << " [fastframe]: Number of traces to be stored in scope buffer before writing to disk." << endl;
  cout << " [maxtime]: Time in seconds after which the program will terminate." << endl << endl;
  cout << "example line: $./teksoft mydata ch=3 10000 200 3600" << endl;
  cout << endl;

}

string cleanOutput( char* buffer ){
    // Clean buffer to stop at endline
    string strbuffer = buffer;
    size_t found = strbuffer.find("\n");
    return strbuffer.substr( 0, found );
}

int main(int argc, char** argv) {
  
  //Internally Set
  int fastframe_numframes = 100;
  string basefilename = "testtrace";
  int NumChannels = 2;
  int TracesRequested = 1000;
  int MaxRunTime = 3600; //seconds

  enum { kBINARY, kASCII };
  int acqmode = kBINARY;

  bool ScreenDumpTrace = false;
  int verbose = 0;

  // SET PARAMETERS ===========================================================

  if (argc<6) {
    if (argc>1) {
      if (strcmp(argv[1], "--help")==0) {
	output_help();
	return 0;
      }
      else if (strcmp(argv[1], "--set")==0) {
	cout << "Using internally set parameters" << endl;
      }
      else {
	cout << "Not Enough Parameters: type --help for parameters" << endl;
	return 0;
      }
    }
    else {
      cout << "Not Enough Parameters: type --help for parameters" << endl;
      return 0;
    }
  }

 
  if (argc==6) {
    basefilename = argv[1];
    string Arg_Channels = argv[2];
    string Arg_Traces = argv[3];
    string Arg_FastFrame = argv[4];
    string Arg_maxtime = argv[5];
    
    sscanf(Arg_Traces.c_str(), "%d", &TracesRequested);
    sscanf(Arg_FastFrame.c_str(), "%d", &fastframe_numframes);
    sscanf(Arg_maxtime.c_str(), "%d", &MaxRunTime);
    sscanf(Arg_Channels.c_str(), "ch=%d", &NumChannels);
  }

  //===========================================================================


  cout << endl << "----------------------------------" << endl;
  cout << "SIMPLE DATA ACQUISITION ROUTINE" << endl;
  string headerfilename = basefilename + "_header.txt";
  string tracefilename = basefilename + "_traces.bin";
  
  cout << "Headerfile: " << headerfilename << endl;
  cout << "Tracefile: " << tracefilename << endl;
  cout << "Channels: " << NumChannels << endl;
  cout << "Fast Frame Traces: " << fastframe_numframes << endl;
  cout << "Traces Requested: " << TracesRequested << endl;
  cout << "Time out: " << MaxRunTime << " seconds" << endl;
  
  int dmm;
  int err = 0;
  char buffer[500];
  char  writebuf[500];
  string command;
  string strbuffer;

  //INITIALIZE DEVICE-------------------
  dmm = ibdev(0, 1, 0, 13, 1, 0);
  ibclr(dmm);
  ibtmo( dmm, T3s );
  sprintf(writebuf, "*IDN?");
  ibwrt(dmm, writebuf, 5);
  ibrd(dmm, buffer, 50);  
  strbuffer = cleanOutput( buffer );
  cout << "OPENED DEVICE: " << strbuffer << endl << endl;
  cout << "---SETTINGS---" << endl;

  //SET SCOPE TO SINGLE ACQUIRE MODE-----
  sprintf(writebuf, "ACQ:STOPAfter SEQUENCE");
  ibwrt(dmm, writebuf, 22); 
  sprintf(writebuf, "ACQ:STOPAfter?");
  ibwrt(dmm, writebuf, 14);
  ibrd(dmm, buffer, 50);
  strbuffer = cleanOutput( buffer );
  cout << "STOP AFTER: " << strbuffer << endl;

  //SET OUPUT FORMAT   --------------------------- 
  for (int i=0; i<NumChannels; i++) {  
    command = "DATa:SOURCE CH";
    sprintf(writebuf, "%s%d", command.c_str(), i+1);
    ibwrt(dmm, writebuf, command.length());
    
    command = "DATa:WIDth 1";
    sprintf(writebuf, "%s", command.c_str());
    ibwrt(dmm, writebuf, command.length());
    
    command = "DATa:ENCdg ASCIi"; //ASCII
    if (acqmode==kASCII) {
	command = "DATa:ENCdg ASCIi"; //ASCII
	cout << "FILEOUTPUT FORMAT: ASCII" << endl;
    }
    else if (acqmode==kBINARY) {
	command = "DATa:ENCdg RIBinary"; //BINARY
	cout << "FILEOUTPUT FORMAT: RIBINARY" << endl;
    }
    else {
	cout << "Invalid acquisition mode." << std::endl;
	assert(false);
    }
    sprintf(writebuf, command.c_str());
    ibwrt(dmm, writebuf, command.length());

    command = "WFMOutpre:BYT_Nr 1";
    sprintf(writebuf, "%s", command.c_str());
    ibwrt(dmm, writebuf, command.length());

  }
  

  //SET UP FAST FRAME--------------------
  int ffstate = 0;
  command = "HOR:FAST:STATE?";
  sprintf(writebuf, command.c_str());
  ibwrt(dmm, writebuf, command.length());
  ibrd(dmm, buffer, 1);
  sscanf(buffer, "%d", &ffstate);
  if (ffstate==0) {
    cout << "FAST FRAME MODE ALREADY OFF." << endl;
  }
  else if (ffstate==1) {
    cout << "FAST FRAME MODE ALREADY ON. TURNING OFF TO RESET." << endl;
    command = "HOR:FAST:STATE 0";
    sprintf(writebuf, command.c_str());
    ibwrt(dmm, writebuf, command.length());
  }
  
  
  //SET FAST FRAME COUNTS (does not seem to be effective)------
  char ff_ch[10];
  string ff_num_str;
  sprintf(ff_ch, "%d", fastframe_numframes);
  ff_num_str = ff_ch;
  command = "HORizontal:FASTframe:COUNT " + ff_num_str;
  sprintf(writebuf, "%s", command.c_str());
  ibwrt(dmm, writebuf, command.length());
  cout << "ACTIVATE FAST FRAME (" << writebuf << ")" << ff_num_str << " " << ff_ch << endl;
  ibwait(dmm,TIMO|RQS);    
  command = "HOR:FAST:STATE ON";
  sprintf(writebuf, command.c_str());
  ibwrt(dmm, writebuf, command.length());
  ibwait(dmm,TIMO|RQS);
  command = "HORizontal:FASTframe:COUNT?";
  sprintf(writebuf, "%s", command.c_str());
  ibwrt(dmm, writebuf, command.length());
  ibwait(dmm,TIMO|RQS);
  ibrd(dmm, buffer, 10);

  //RETRIEVE SCOPE PARAMETERS--------------------------
  float Parameters[4][8];
  enum { kVperADC, kYADCOffset, kBytesPerPoint, kPointsPerTrace, kYZero, kSecPerTDC, kTracesPerFrame, kNumberOfTraces };
  for (int ch=0; ch<NumChannels; ch++) {
    

    //Set Channel
    char channelinput[30];
    sprintf(channelinput, "data:source CH%d", ch+1);
    command = channelinput;
    cout << "GETTING PARAMETERS FOR CH " << ch+1 << ": " << command << endl;
    sprintf(writebuf, "%s", channelinput);
    ibwrt(dmm, writebuf, command.length());
    
    //Voltage Multiplier
    command = "WFMPre:YMUlt?";
    sprintf(writebuf, command.c_str());
    ibwrt(dmm, writebuf, command.length());
    ibrd(dmm, buffer, 20);
    sscanf(buffer, "%e", &Parameters[ch][kVperADC] );
    //Offset Voltage
    command = "WFMPre:YOFf?";
    sprintf(writebuf, command.c_str());
    ibwrt(dmm, writebuf, command.length());
    ibrd(dmm, buffer, 20);
    sscanf(buffer, "%f", &Parameters[ch][kYADCOffset]);
    //Bytes per Point
    command = "WFMPre:BYT_Nr?";
    sprintf(writebuf, command.c_str());
    ibwrt(dmm, writebuf, command.length());
    ibrd(dmm, buffer, 20);
    sscanf(buffer, "%f", &Parameters[ch][kBytesPerPoint]);
    cout << "BYT_NR: " << Parameters[ch][kBytesPerPoint] << endl;

    //Total Number of Points per Trace
    command = "WFMPre:NR_Pt?";
    sprintf(writebuf, command.c_str());
    ibwrt(dmm, writebuf, command.length());
    ibrd(dmm, buffer, 20);
    sscanf(buffer, "%f", &Parameters[ch][kPointsPerTrace]);    

    //test-------//
    cout << "points in trace (from teksoft): " << Parameters[ch][kPointsPerTrace] << endl;
    //-----------//

    //Trigger Offset
    command = "WFMPre:YZEro?";
    sprintf(writebuf, command.c_str());
    ibwrt(dmm, writebuf, command.length());
    ibrd(dmm, buffer, 20);
    sscanf(buffer, "%f", &Parameters[ch][kYZero]);
    //Time Interval per Point
    command = "WFMOutpre:XINcr?";
    sprintf(writebuf, command.c_str());
    ibwrt(dmm, writebuf, command.length());
    ibrd(dmm, buffer, 20);
    sscanf(buffer, "%f", &Parameters[ch][kSecPerTDC]);

    //Number of Frames 
    command = "HORizontal:FASTframe:COUNT?";
    sprintf(writebuf, "%s", command.c_str());
    ibwrt(dmm, writebuf, command.length());
    ibwait(dmm,TIMO|RQS);
    ibrd(dmm, buffer, 20);
    ibwait(dmm,TIMO|RQS);
    sscanf(buffer, "%f", &Parameters[ch][kTracesPerFrame]);

    Parameters[ch][kNumberOfTraces] = TracesRequested;
    
  }//end of channel setting loop
  
  //OUTPUT HEADERFILE------------------------------
  fstream headerfile(headerfilename.c_str(), fstream::out);
  for (int ch=0; ch<NumChannels; ch++) {
      cout << "CHANNEL " << ch+1 << " PARAMETERS: ";
      for (int par=0; par<8; par++) {
	  headerfile << Parameters[ch][par] << " ";
	  cout << Parameters[ch][par] << " ";
      }
      headerfile << endl;
      cout << endl;
  }
  headerfile.close();


  // ACQUISITION LOOP-----------------------------------------
  int tracesread = 0;
  fstream tracefile(tracefilename.c_str(), fstream::out);
  cout << "TRACES REQUESTED: " << TracesRequested << endl;
  cout << "MAX RUN TIME: " << MaxRunTime << " seconds" << endl;
  time_t RunTimeStart = time(NULL);
  time_t RunTime = time(NULL);


  while (tracesread<TracesRequested*NumChannels && MaxRunTime > difftime(RunTime, RunTimeStart)) {
    
    //START ACQUISITION------------------------------
    command = "ACQ:STATE RUN";
    sprintf(writebuf, command.c_str());
    ibwrt(dmm, writebuf, command.length());

    //WAIT FOR ACQUITION RETURN----------------------
    if (verbose>0)
	cout << endl << "===WAITING FOR DATA AFTER " << command << " ===" << endl; 
    command = "*OPC?";
    sprintf(writebuf, command.c_str());
    time_t acq_timeout = time(NULL) + 60; //in seconds -> 5 minutes (need to be so long?)
    int acq_status = 0;

    while (time(NULL) < acq_timeout) {
	ibwrt(dmm, writebuf, command.length());
	ibrd(dmm, buffer, 5);
	sscanf(buffer, "%d", &acq_status);
	//FOR DEBUGGING
	if (verbose>0) {
	    cout << "Polling: " << writebuf << " --> ";
	    cout << " Status: " << acq_status << endl;
	    cout << "UNTIL ACQ TIMEOUT: " << acq_timeout - time(NULL) << endl;
	}
	if (acq_status==1) {
	    if (verbose>0)
		cout << "WAVEFORM(S) ACQUIRED" << endl;
	    break;
	}
	sleep(1); //Pause for One second
    }
    if (acq_status==0) {
      cout << "ACQUISTION TIME OUT" << endl;
      cout << "END PROGRAM" << endl;
      ibonl(dmm, 0);
      return 0;
    }
    
    
	
//     //ASCII-----------------------------------  
//     char* trace[4];
//     string chstring;
//     char ch_char[5];
//     for (int ch=0; ch<NumChannels; ch++) {
    
// 	sprintf(ch_char, "CH%d", ch+1);
// 	chstring = ch_char;
// 	//ALLOCATE MEMORY FOR FRAMES
// 	int frames = int(Parameters[ch][6]);   
// 	cout << "ALLOCATE MEMORY, FRAMES: " << frames << endl;
// 	cout << "CHANNEL: " << ch << endl;
// 	const int numpoints =  int(Parameters[ch][6]*(Parameters[ch][3]*200));
// 	trace[ch] = new char[ numpoints ];

// 	//if ((trace[ch] = (char**)malloc((size_t)(frames))) == NULL) {
// 	//cout << "OUT OF MEMORY" << endl;
// 	//return 0;
// 	//}
	
// 	//CALL CHANNEL
// 	cout << "CALL CHANNEL, Buffer: ";
// 	command = "data:source " + chstring;
// 	sprintf(writebuf, "%s", command.c_str());
// 	cout << writebuf << endl;
// 	ibwrt(dmm, writebuf, command.length());    
// 	ibwait(dmm, TIMO|RQS);
// 	command = "DATa:SOUrce?";
// 	sprintf(writebuf, "%s", command.c_str());
// 	ibwrt(dmm, writebuf, command.length());
// 	ibrd(dmm, buffer, 4);
// 	buffer[4] = '\0';
// 	cout << "SOURCE: " << buffer << endl;
   
// 	ibwait(dmm, TIMO|RQS);


// 	//CALL WAVEFORM
// 	command = "CURVe?";
// 	sprintf(writebuf, command.c_str());
// 	unsigned short command_status = ibwrt(dmm, writebuf, command.length());
// 	cout << "WAVEFORM CALLED, CHANNEL " << ch+1 << endl;
// 	//if ( (command_status & (1<<15) )!=0 || (command_status & (1<<14) )!=0) {
// 	if ( command_status!=2304 && command_status!=10496) {
// 	    cout << "ERROR from ibwrt CURVe?: " << command_status << endl;
// 	    for (int bit=0; bit<16; bit++) {
// 		unsigned short flag = (1<<bit);
// 		if ( (command_status & flag) != 0 )
// 		    cout << "  ERROR BIT " << bit+1 << " set" << endl;
// 		else
// 		    cout << "  ERROR BIT " << bit+1 << " not set" << endl;
// 	    }
// 	    return 0;
// 	}
// 	ibwait(dmm, TIMO|RQS);
// 	cout << "   reading points (parameter 3):" << Parameters[ch][3] << endl;
// 	cout << "   number of traces (parameter 6):" << Parameters[ch][6] << endl;
// 	//for (int i=0; i<int(Parameters[ch][6]);i++) {
// 	//if ((trace[ch][i] = (char*)malloc((size_t)(Parameters[ch][3]*10*3))) == NULL) {
// 	//cout << "OUT OF MEMORY" << endl;
// 	//return 0;
// 	//}
// 	//ibrd(dmm, trace[ch], numpoints);
// 	//cout << "READ WAVEFORM " << i << endl;
	    
// 	command_status = ibrd(dmm, trace[ch], numpoints);
// 	if ( command_status!=2304 && command_status!=10496 ) {
// 	    cout << "READ ERROR: command status " << command_status << endl;
// 	    for (int bit=0; bit<16; bit++) {
// 		unsigned short flag = (1<<bit);
// 		if ( (command_status & flag) != 0 )
// 		    cout << "  ERROR BIT " << bit+1 << " set" << endl;
// 		else
// 		    cout << "  ERROR BIT " << bit+1 << " not set" << endl;
// 	    }
// 	    cout << "READ ERROR: iberr " << iberr << endl;
// 	    return 0;
// 	}

// 	//tracefile << trace[ch][i] << endl << endl;

// 	//Now write the data to the output file
// 	//the conditional is due to the behavior of strtok,
// 	//it must be run once with the string to be tokenized as an arg,
// 	//and subsequently with NULL as an argument.
	
// 	//tracefile << trace[ch] << endl;

// 	int trace_counter;
// 	int point_counter;

// 	for (trace_counter=0; trace_counter<Parameters[ch][6]; trace_counter++)
// 	{

// 		if (trace_counter==0)
// 		{
// 			tracefile << strtok (trace[ch], ",\n") << ",";
// 			for(point_counter=0; point_counter<Parameters[ch][3]-1; point_counter++)
// 			{
// 				tracefile << strtok(NULL, ",\n") << ","; //Separate the data into traces 
// 			}
			
// 		}
// 		else
// 		{
// 			for(point_counter=0; point_counter<Parameters[ch][3]; point_counter++)
// 			{
// 				tracefile << strtok(NULL, ",\n") << ","; //Separate the data into traces 
// 			}
			
// 		}
	
// 		tracefile << endl; //At the end of each trace, end the line and add a newline.

// 	}

// 	//cout << "WAVEFORM: " << trace[ch][i] << endl;
// 	tracesread += int(Parameters[ch][6]);

//     }//end of loop over channels

//     //FREE MEMORY, ASCII----------------------------
//     cout << "FREE MEMORY" << endl;
//     for (int ch=0; ch<NumChannels;ch++) {
// 	//for (int i=0; i<int(Parameters[ch][6]);i++) {
// 	//FREE TRACES IN FRAME
// 	//free(trace[ch][i]);
// 	cout << "FREE FRAME BUFFER" << endl;
// 	delete [] trace[ch];
// 	//}
// 	//free(trace[ch]);
// 	cout << "FREE CHANNEL" << endl;
//     }
    
  
    //READ DATA, BINARY------------------------------------------ 
    // We ask for the data to come in 2 bytes

    char** tracedata[4];
    string chstring;
    char ch_char[5];
    int bytestreamlength = 0;

    for (int ch=0; ch<NumChannels; ch++) {
	
	//ALLOCATE MEMORY FOR A FRAME
	int numtraces = int(Parameters[ch][kTracesPerFrame]);
	tracedata[ch] = new char*[numtraces]; // allocating pointers to traces
	
	//GET WAVEFORM------------------------------    
	//SET CHANNEL TO GET TRACES
	sprintf(ch_char, "CH%d", ch+1);
	chstring = ch_char;
	command = "data:source " + chstring;
	sprintf(writebuf, "%s%d", command.c_str(), ch+1);
	ibwrt(dmm, writebuf, command.length());    
	command = "DATa:SOUrce?";
	sprintf(writebuf, "%s", command.c_str());
	ibwrt(dmm, writebuf, command.length());
	ibrd(dmm, buffer, 4);
	if (verbose>0)
	    cout << "SET CHANNEL SOURCE: " << cleanOutput(buffer) << endl;;
	ibwait(dmm, TIMO|RQS);
	
	//CALL WAVEFORM
	command = "CURVe?";
	sprintf(writebuf, command.c_str());
	ibwrt(dmm, writebuf, command.length());
	if (verbose>0)
	    cout << "REQUEST WAVEFORM CALLED, CHANNEL " << ch+1 << endl;
	ibwait(dmm, TIMO|RQS);
	
	// BINARY DATA COMES AS:
	// #<x><yyy><data><newline>
	// <x> = number of y bytes for each point
	// <yyy> = number of bytes to transfer
	// <data> is the binary
	// <newline> = 1 byte newline character
	
	if (verbose>0)
	    cout << "-- waveform binary predata --" << endl;
	
	//READ # SYMBOL
	char c[2];
	ibrd(dmm, &c, 1);
	c[1] = '\0';
	if (verbose>0)
	    cout << "New data: Pound it! " << cleanOutput(c) << endl;
	
	//READ NUMBER OF BYTES TO BE READ
	int len;
	ibrd(dmm, &c, 1);
	c[1] = '\0';
	len = atoi(&c[0]);
	if (verbose>0)
	    cout << "Length of byte width info " << c << " "  << len << endl;
	
	//READ STRING CONTAINING NUMBER OF BYTES TO TRANSFER
	char recordl[20];
	if(ibrd(dmm,recordl,len) & ERR)
	    cout << "ERROR, recordl" << endl;
	recordl[len] = '\0';
	bytestreamlength = atoi(recordl);
	if (verbose>0) {
	    cout << "Total bytes to transfer: " << bytestreamlength << endl;
	    cout << "---------------------------------------" << endl;
	}
	
	// Number of points per trace in the frame
	const int tracepoints = (bytestreamlength/int(Parameters[ch][kBytesPerPoint]))/int(Parameters[ch][kTracesPerFrame]);
	
	//COLLECT TRACE FOR EACH FRAME
	for (int trace=0; trace<int(Parameters[ch][kTracesPerFrame]);trace++) {
	    
	    //ALLOCATING TRACESIZE
	    // Need to know the number of bytes a char is on this machine -- it's not always the same!
	    int charsize = sizeof(char);
	    int ncharspertrace = tracepoints*int(Parameters[ch][kTracesPerFrame])/charsize;
	    if (verbose>0)
		cout << "ALLOCATING MEM FOR TRACE " << trace 
		     << " (char=" << charsize << " bytes) :" 
		     <<  tracepoints << " points" << endl;
	    tracedata[ch][trace] = new char[ncharspertrace]; 
	    
	    if (tracedata[ch][trace] == NULL ) {
		// to do this properly i need to throw and catch exceptions
		// i dont know if this even works
		cout << "OUT OF MEMORY" << endl;
		return 0;
	    }
	    
	    err = ibrd(dmm, tracedata[ch][trace], tracepoints);
	    if (err & ERR)
		cout << "ERROR, READING TRACE FOR FRAME " << trace << endl;
	    
	    tracesread++;
	}//end of trace loop
    }//end of channel waveform acquisition loop

    const int NUMTRACES = int(Parameters[0][kTracesPerFrame]);
    const int NUMPOINTS = int(Parameters[0][kPointsPerTrace]);

    //TRANSLATE, for debugging-----------------------------------

    if (ScreenDumpTrace) {
	cout << "--------------------------------------------------" << endl;
	cout << " Screen dumping trace, you're welcome." << endl;
    }

    int** DataADC[4];
    for (int ch=0; ch<NumChannels; ch++) {
	//ALLOCATING DATA, FRAME
	DataADC[ch] = new int*[NUMTRACES];
	if (verbose>0)
	    cout << "TRANSLATE CHANNEL " << ch+1 << endl;
	for (int trace=0; trace<int(Parameters[ch][kTracesPerFrame]);trace++) {
	    DataADC[ch][trace] = new int[NUMPOINTS];

	    if (ScreenDumpTrace)
		cout << "Trace " << trace << "----------------------------" << endl;

	    for (int pt=0; pt<NUMPOINTS; pt++) {
		
		// convert the char into an int
		if ( int(Parameters[ch][kBytesPerPoint])==1 ) {
		    // Easy peasy
		    DataADC[ch][trace][pt] = int(tracedata[ch][trace][pt]);
		}
		else if (int(Parameters[ch][kBytesPerPoint])==2 ) {
		    // Assuming most sig byte first (RIBINARY).  If SRIBINARY: good luck.
		    char zpoint[2];
		    zpoint[0] = tracedata[ch][trace][2*pt];
		    zpoint[1] = tracedata[ch][trace][2*pt+1];
		    DataADC[ch][trace][pt] = int(*zpoint);
		}
		
// 		    // this was copied, so i dont know what it is doing
// 		    //twob = (int(trace[ch][i][pt]) || int(trace[ch][i][pt+1]));
// 		    //double twob = ((double)cheattrace[pt] || (double)cheattrace[pt+1]*256);
// 		    //float onea = float(cheattrace[pt]);
// 		    //float oneb = float(cheattrace[pt+1])*256;
// 		    float onea = float(trace[ch][i][pt]);
// 		    float oneb = float(trace[ch][i][pt+1]);
// 		    Data[ch][i][pt/2] = int(onea);
// 		    //Data[ch][i][pt+1] = int(oneb);
// 		    //if (onea!=0)
// 		    //  value=onea;
// 		    //else
// 		    //  value=oneb;
// 		    float value = float(Data[ch][i][pt/2]*256);
// 		    //if (oneb!=0)
// 		    //  value=onea*oneb;
// 		    point = (value-int(Parameters[ch][1]))*Parameters[ch][0] + float(Parameters[ch][4]);
// 		    cout << (pt)/2 << ": " << point << " " << onea << " " << oneb << " ";

		float voltage = Parameters[ch][kVperADC]*(DataADC[ch][trace][pt]-int(Parameters[ch][kYADCOffset]));
		voltage -= Parameters[ch][kYZero];
		if (ScreenDumpTrace)
		    cout << voltage << " ";
		    
	    }//end of point loop

	    if (ScreenDumpTrace) {
		cout << "------------------------------------ end of channel " << ch+1 << ", trace " << trace;
		cout << " (traces read: " << tracesread << ")";
		cout << " [hit enter to continue]";
		cin.get();
	    }
	}//end of trace loop
    }//end of channel llop
    if (verbose>0)
	cout << endl << endl;

    //STORE IN FILE----------------------------------
    
    for (int trace=0; trace<NUMTRACES;trace++) {
	for (int ch=0;ch<NumChannels;ch++){
	    
// 	    if (acqmode == kBINARY ) {
// 		tracefile << *tracedata[ch][trace] << endl; // dump the whole trace into the file
// 	    }
// 	    else if (acqmode==kASCII) {
	    for (int pt=0; pt<int(Parameters[ch][kPointsPerTrace]);pt++) {
		char zpt[10];
		sprintf(zpt, "%d", DataADC[ch][trace][pt] );
		tracefile << zpt << " ";
	    }
//	    }
	    tracefile << endl;
	}
	
    }	
    
    //FREE MEMORY----------------------------
    if (verbose>0)
	cout << "FREE MEMORY" << endl;
    for (int ch=0; ch<NumChannels;ch++) {
	for (int trace=0; trace<int(Parameters[ch][kTracesPerFrame]);trace++) {
	    //FREE TRACE
	    delete [] tracedata[ch][trace];
	    delete [] DataADC[ch][trace];
	}
	// Free Channel
	delete[] tracedata[ch];
	delete[] DataADC[ch];
    }
    
    RunTime = time(NULL);
    if (verbose>0) {
	cout << "STORED " << tracesread/NumChannels << " OF " << TracesRequested << " TRACES" << endl;
	cout << "TIME ELASPED " << difftime(RunTime, RunTimeStart) << " SECONDS." << endl;
    }

    if (  MaxRunTime < difftime(RunTime, RunTimeStart) )
	cout << "Program max time reached. Quitting acquisition loop." << endl;

    if ( (tracesread/NumChannels)%100==0)
	cout << "Traces read: " << tracesread/NumChannels << endl;

  }//end of while loop
  
  tracefile.close();
  cout << "TOTAL TRACES STORED: " << tracesread/NumChannels << endl;
  
  //RESTORE OPERATION---------------------------
  //TURN FAST FRAME OFF
  command = "HOR:FAST:STATE 0";
  sprintf(writebuf, command.c_str());
  ibwrt(dmm, writebuf, command.length());
  //SET SCOPE ACQ MODE BACK TO RUN
  command = "ACQ:STOPAfter RUNSTop";
  sprintf(writebuf, command.c_str());
  ibwrt(dmm, writebuf, command.length());
  command = "ACQ:STATE ON";
  sprintf(writebuf, command.c_str());
  ibwrt(dmm, writebuf, command.length());
  //DEVICE OFFLINE-----------------------
  ibonl(dmm, 0);
  
  cout << "END OF PROGRAM" << endl;

  return 0;
  
}
